﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Timers;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace lemon
{
    public partial class Form1 : Form
    {
        const string PID = "0085";// 项目ID*
        const int NUM = 1;// 获取手机号条数（1 - 10）*
        const int NOBLACK = 1;// 过滤黑名单规则（0，1）：0:只过滤自己添加的黑名单，1:过滤所有用户添加的黑名单*
        const int SERIAL = 2;//是否多条(1:为多条, 2为单条) *
        public List<CountryCodeMapping> CountryList { set; get; }

        public bool Running { set; get; } = false;
        public bool isLogin { set; get; }
        public string acc { set; get; }
        public string pwd { set; get; }
        public static List<Task> tasklst;//多个任务

        System.Timers.Timer timer;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ReadUser();
            init();

            Thread t = new Thread(new ThreadStart(GetData));
            t.IsBackground = true;
            t.Start();
        }


        public void init()
        {
            //项目ID 0085 支付宝
            isLogin = false;
            //数据源为一个string数组

            ddlCountry.DataSource = newCountryList();
            ddlCountry.ValueMember = "Abbr2";
            ddlCountry.DisplayMember = "Name";
            initMobileCode();
        }


        public void ReadUser()
        {
            //TODO:设置Task
            User user = new User();
            //  读取配置文件寻找记住的用户名和密码
            FileStream fs = new FileStream("data.bin", FileMode.OpenOrCreate);
            if (fs.Length > 0)
            {
                BinaryFormatter bf = new BinaryFormatter();
                user = bf.Deserialize(fs) as User;
                txtAcc.Text = user.Username;
                txtPwd.Text = user.Password;
            }
            fs.Close();
        }

        public void WriteUser(string acc,string pwd)
        {
            User user = new User();
            FileStream fs = new FileStream("data.bin", FileMode.Create);
            BinaryFormatter bf = new BinaryFormatter();
            user.Username = acc;
            user.Password = pwd;

            //要先将User类先设为可以序列化(即在类的前面加[Serializable])
            bf.Serialize(fs, user);
            fs.Close();
        }

        public List<CountryCodeMapping> newCountryList()
        {
            List<CountryCodeMapping> lst = new List<CountryCodeMapping>();
            var jobect = JsonReaderN.GetJObjectFromFile("JSON/CountryCodeJson.json");
            var data = jobect.Value<JArray>("data");
            foreach(var item in data)
            {
                var ccmItem = JsonConvert.DeserializeObject<CountryCodeMapping>(item.ToString());
                lst.Add(ccmItem);
            }
            CountryList = lst;
            return lst;

        }
        public void initMobileCode()
        {
            string abbr2 = ddlCountry.SelectedValue.ToString();
            var one = CountryList.FirstOrDefault(x => x.Abbr2 == abbr2);
            if (one != null)
            {
                txtMobileCode.Text = "+" + one.Code.ToString();
            }
        }

        /// <summary>
        /// 登陆
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLogin_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtAcc.Text))
            {
                MessageBox.Show("账号不能为空！");
                return;
            }
            if (string.IsNullOrEmpty(txtPwd.Text))
            {
                MessageBox.Show("密码不能为空！");
                return;
            }
            getUserInfo();
        }

        public bool isValid()
        {
            if (string.IsNullOrEmpty(acc))
            {
                MessageBox.Show("账号不能为空！");
                return false;
            }
            if (string.IsNullOrEmpty(pwd))
            {
                MessageBox.Show("密码不能为空！");
                return false;
            }
            return true;
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        public void getUserInfo()
        {
            string url = string.Format("getUserInfo?name={0}&pwd={1}", txtAcc.Text, txtPwd.Text);
            var json = ApiHelper.HttpApi(url);
            var obj = JObject.Parse(json);
            var code = obj.GetValue<int>("code");
            var msg = obj.GetValue<string>("msg");
            if (code == 200)
            {
                JObject data = obj.Value<JObject>("data");
                if (data != null)
                {
                    var score = data.GetValue<string>("score");
                    lblScore.Text = score;
                }
                if (!isLogin)
                {
                    isLogin = true;
                    acc = txtAcc.Text;
                    pwd = txtPwd.Text;
                    WriteUser(txtAcc.Text, txtPwd.Text);
                    btnLogin.Enabled = false;
                }
            }
            else
            {
                MessageBox.Show(msg);
            }

        }

        /// <summary>
        /// 获取验证码
        /// </summary>
        public void GetCode()
        {
            if (!Running)
            {
                timer.Stop();
                return;
            }
            if(string.IsNullOrEmpty(txtMobileCode.Text) || string.IsNullOrEmpty(txtMobile.Text))
            {
                MessageBox.Show("手机号不能为空！");
                return;
            }

            var mobile = txtMobileCode.Text + txtMobile.Text;
            string url = string.Format("getMsg?name={0}&pwd={1}&pn={2}&pid={3}&serial={4}", acc, pwd, mobile, PID, SERIAL);

            var json = ApiHelper.HttpApi(url);
            var obj = JObject.Parse(json);
            var code = obj.GetValue<int>("code");
            var msg = obj.GetValue<string>("msg");
            if (code == 200)
            {
                string data = obj.Value<string>("data");
                txtCode.Text = data;
                timer.Stop();//停止获取验证码
            }
            else
            {
                txtCode.Text = "暂未收到验证码，请耐心等待...";
            }
        }
        /// <summary>
        /// 释放手机号
        /// </summary>
        public void passMobile()
        {
            var mobile = txtMobileCode.Text + txtMobile.Text;
            string url = string.Format("passMobile?name={0}&pwd={1}&pn={2}&pid={3}&serial={4}", acc, pwd, mobile, PID, SERIAL);

            var json = ApiHelper.HttpApi(url);
            var obj = JObject.Parse(json);
            var code = obj.GetValue<int>("code");
            var msg = obj.GetValue<string>("msg");
            if (code == 200)
            {
                string data = obj.Value<string>("data");
            }
            else
            {
                MessageBox.Show(msg);
            }
        }
        /// <summary>
        /// 手机号码加黑名单
        /// </summary>
        public void addBlack()
        {
            var mobile = txtMobileCode.Text + txtMobile.Text;
            string url = string.Format("addBlack?name={0}&pwd={1}&pn={2}&pid={3}", acc, pwd, mobile, PID);

            var json = ApiHelper.HttpApi(url);
            var obj = JObject.Parse(json);
            var code = obj.GetValue<int>("code");
            var msg = obj.GetValue<string>("msg");
            if (code == 200)
            {
                string data = obj.Value<string>("data");
                timer.Stop();
                getUserInfo();//更新余额
            }
            else
            {
                MessageBox.Show(msg);
            }
        }

        /// <summary>
        /// 取号  含快捷键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGetNumber_Click(object sender, EventArgs e)
        {
            //
            //txtMobile.Text = "无号,等待中...";

            if (!isValid()) return;
            btnGetNumber.Enabled = false;
            tasklst = new List<Task>();
            var cuy = ddlCountry.SelectedValue.ToString();
            var cts = new CancellationTokenSource();
            Running = true;
            ValidGetMobile(cuy, cts);
           // ValidGetMobile(cuy, "getMobileCode", cts);

            //注册一个线程取消后执行的逻辑
            //cts.Token.Register(() =>
            //{
            //    //这里执行线程被取消后的业务逻辑.
            //  //  Console.WriteLine("-------------我是线程被取消后的业务逻辑---------------------");
            //    timer.Start();
            //});
        }
        public void ValidGetMobile(string cuy, CancellationTokenSource cts)
        {
            if (!Running)
            {
                return;
            }
            GetMobile(cuy, cts);

            var task = GetMobile(cuy, cts);
            tasklst.Add(task);
            task.ContinueWith(t => {
                var token = cts.Token;
                var result = t.Result;
                if (result == null) return;
                var code = result.GetValue<int>("code");
                var msg = result.GetValue<string>("msg");
                MethodInvoker invoker = () =>
                {
                    if (code == 200)
                    {
                        cts.Cancel();
                        if (token.IsCancellationRequested && Running)
                        {
                            string data = result.Value<string>("data");
                            var pre = txtMobileCode.Text;
                            txtMobile.Text = data.Substring(pre.Length);
                            btnGetNumber.Enabled = true;//释放取号按钮
                            Running = false;
                            //-------------我是线程被取消后的业务逻辑---------------------
                            Task.WhenAll(tasklst.ToArray()).ContinueWith((s) =>
                            {
                                timer.Start();
                            });
                        }

                    }
                    else if (code == 906 || code == 400)
                    {
                        txtMobile.Text = "无号,等待中...";
                        ValidGetMobile(cuy, cts);
                    }
                    else
                    {
                        btnGetNumber.Enabled = true;//释放取号按钮
                        MessageBox.Show(msg);
                    }
                };
                if (txtMobile.InvokeRequired || btnGetNumber.InvokeRequired)
                {
                    Invoke(invoker);
                }//跨线程的使用Invoke更新
                else
                { invoker(); }//同线程的直接更新

             
            });
        }
        
        private Task<JObject> GetMobile(string cuy,CancellationTokenSource cts)
        {
            return Task<JObject>.Run(() =>
            {
                string action = "getMobile";
                Random rand = new Random();
                if (rand.Next(0, 2) == 0)
                {
                    action = "getMobile";
                }
                else
                {
                    action = "getMobileCode";
                }

                var token = cts.Token;
                if (token.IsCancellationRequested) { Thread.Sleep(500); return null; }
                var url = $"{action}?name={acc}&pwd={pwd}&cuy={cuy}&pid={PID}&num={NUM}&noblack={NOBLACK}&serial={SERIAL}&done=1";
                var json = ApiHelper.HttpApi(url);
                var obj = JObject.Parse(json);
                var result = JObject.Parse(json);
                return result;
                //var code = result.GetValue<int>("code");
                //var msg = result.GetValue<string>("msg");
                //if (code == 200)
                //{
                //    cts.Cancel();
                //    if (token.IsCancellationRequested && Running)
                //    {
                //        string data = result.Value<string>("data");
                //        var pre = txtMobileCode.Text;

                //        MethodInvoker invoker = () =>
                //        {
                //            txtMobile.Text = data.Substring(pre.Length);
                //            btnGetNumber.Enabled = true;//释放取号按钮
                //        };
                //        if (txtMobile.InvokeRequired)
                //        {
                //            Invoke(invoker);
                //        }//跨线程的使用Invoke更新
                //        else
                //        { invoker(); }//同线程的直接更新
                //        Running = false;
                //    }
                    
                //}
                //else if (code == 906 || code == 400)
                //{
                //    MethodInvoker invoker = () =>
                //    {
                //        txtMobile.Text = "无号,等待中...";
                //    };
                //    if (txtMobile.InvokeRequired)
                //    {
                //        Invoke(invoker);
                //    }//跨线程的使用Invoke更新
                //    else
                //    { invoker(); }//同线程的直接更新
                //    ValidGetMobile(cuy,action, cts);
                //}
                //else
                //{
                //    MethodInvoker invoker = () =>
                //    {
                //        btnGetNumber.Enabled = true;//释放取号按钮
                //    };
                //    if (btnGetNumber.InvokeRequired)
                //    {
                //        Invoke(invoker);
                //    }//跨线程的使用Invoke更新
                //    else
                //    { invoker(); }//同线程的直接更新
                //    MessageBox.Show(msg);
                //}
            });
        }

        /// <summary>
        /// 释放加黑
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddBlack_Click(object sender, EventArgs e)
        {
            if (!isValid()) return;
            if (string.IsNullOrEmpty(txtMobileCode.Text) || string.IsNullOrEmpty(txtMobile.Text))
            {
               // MessageBox.Show("手机号不能为空！");
                return;
            }
            passMobile();
            addBlack();
            txtCode.Text = "[号码已释放]";
        }

        private void ddlCountry_SelectedIndexChanged(object sender, EventArgs e)
        {
            initMobileCode();
        }

        //取号之后自动获取验证码
        private void GetData()
        {
            timer = new System.Timers.Timer();
            timer.Interval = 1000;
            timer.Enabled = true;
            timer.AutoReset = true;//设置是执行一次（false）还是一直执行(true)；  
            timer.Start();
            timer.Stop();
            timer.Elapsed += (o, a) =>
            {
                SetData();
            };
        }

        //声明委托
        private delegate void SetDataDelegate();
        private void SetData()
        {
            // invokeRequired 获取一个bool值 判断调用控件是否必须要调用invoke方法
            // 如果调用对象在其他线程，则返回true，否则返回false
            if (this.InvokeRequired)//同步调用，阻塞当前线程 改用begininvoke
            {
                this.Invoke(new SetDataDelegate(SetData));
            }
            else
            {
                if (!isLogin)
                {
                    timer.Stop(); return;
                }
                GetCode();
            }
        }
    }
}
